﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text.Json;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using zijian666.Converts;
using zijian666.Converts.Convertor.Extra;
using zijian666.Converts.Factory;
using zijian666.Converts.Json;

namespace UnitTest
{
    [TestClass]
    public class 各种bug
    {
        [TestMethod]
        public void 测试转集合接口()
        {
            var arr = new[] { 1, 2, 3, 4, 5 };

            {
                var list = arr.To<List<int>>();

                Assert.IsNotNull(list);
                Assert.AreEqual(5, list.Count);
                Assert.AreEqual(1, list[0]);
                Assert.AreEqual(2, list[1]);
                Assert.AreEqual(3, list[2]);
                Assert.AreEqual(4, list[3]);
                Assert.AreEqual(5, list[4]);
            }

            {
                var list = arr.To<IList<int>>();

                Assert.IsNotNull(list);
                Assert.AreEqual(5, list.Count);
                Assert.AreEqual(1, list[0]);
                Assert.AreEqual(2, list[1]);
                Assert.AreEqual(3, list[2]);
                Assert.AreEqual(4, list[3]);
                Assert.AreEqual(5, list[4]);
            }

            {
                var list = arr.To<IList>();

                Assert.IsNotNull(list);
                Assert.AreEqual(5, list.Count);
                Assert.AreEqual(1, list[0]);
                Assert.AreEqual(2, list[1]);
                Assert.AreEqual(3, list[2]);
                Assert.AreEqual(4, list[3]);
                Assert.AreEqual(5, list[4]);
            }

            {
                var result = arr.Convert<IMyList<int>>();
                Assert.IsFalse(result.Success);
                System.Console.WriteLine(result.Exception.Message);
                Assert.IsTrue(result.Exception.Message.Contains("无法生成") && result.Exception.Message.Contains("类型的转换器"));
            }

            {
                var result = arr.Convert<IMyList>();
                Assert.IsFalse(result.Success);
                System.Console.WriteLine(result.Exception.Message);
                Assert.IsTrue(result.Exception.Message.Contains("无法生成") && result.Exception.Message.Contains("类型的转换器"));
            }
        }

        [TestMethod]
        public void 测试转NameValueCollection子类()
        {
            var value = new Dictionary<string, string>
            {
                ["a"] = "x",
                ["b"] = "y",
                ["c"] = "z",
            };
            var nv1 = value.To<NameValueCollection>();
            Assert.IsNotNull(nv1);
            Assert.AreEqual(3, nv1.Count);
            Assert.AreEqual("x", nv1["a"]);
            Assert.AreEqual("y", nv1["b"]);
            Assert.AreEqual("z", nv1["c"]);

            var nv2 = value.To<MyNameValueCollection>();
            Assert.IsNotNull(nv2);
            Assert.AreEqual(3, nv2.Count);
            Assert.AreEqual("x", nv2["a"]);
            Assert.AreEqual("y", nv2["b"]);
            Assert.AreEqual("z", nv2["c"]);
        }

        [TestMethod]
        public void 测试Hashtable子类()
        {
            var value = new Dictionary<string, string>
            {
                ["a"] = "x",
                ["b"] = "y",
                ["c"] = "z",
            };
            {
                var result = value.To<Hashtable>();
                Assert.IsNotNull(result);
                Assert.AreEqual(3, result.Count);
                Assert.AreEqual("x", result["a"]);
                Assert.AreEqual("y", result["b"]);
                Assert.AreEqual("z", result["c"]);
            }

            {
                var result = value.To<MyHashtable>();
                Assert.IsNotNull(result);
                Assert.AreEqual(3, result.Count);
                Assert.AreEqual("x", result["a"]);
                Assert.AreEqual("y", result["b"]);
                Assert.AreEqual("z", result["c"]);
            }
        }

        [TestMethod]
        public void DBNull转String()
        {
            var x = Converts.Convert(DBNull.Value, typeof(string));
            Assert.IsTrue(x.Success);
            Assert.IsNull(x.Value);
        }

        [TestMethod]
        public void 测试json转数组加字典()
        {
            var json = "[{\"id\":1,\"name\":\"zijian666\",\"enabled\":true},{\"id\":2,\"name\":\"张三\",\"enabled\":false}]";
            var result = json.Convert<Dictionary<string, dynamic>[]>();
            Assert.IsTrue(result.Success);
            Assert.AreEqual(2, result.Value.Length);
            Assert.AreEqual(1, (int)result.Value[0]["id"]);
            Assert.AreEqual("zijian666", (string)result.Value[0]["name"]);
            Assert.AreEqual(true, (bool)result.Value[0]["enabled"]);
            Assert.AreEqual(2, (int)result.Value[1]["id"]);
            Assert.AreEqual("张三", (string)result.Value[1]["name"]);
            Assert.AreEqual(false, (bool)result.Value[1]["enabled"]);
            var list = new List<object>();
            list.AddRange(result.Value);

        }

        [TestMethod]
        public void 测试动态类型转JSON()
        {
            var json = "{\"id\":1,\"name\":\"zijian666\",\"enabled\":true}";
            var dy = json.To<Dictionary<string, dynamic>>();
            var options = new JsonSerializerOptions
            {
                Converters = {
                    JsonConverters.ProxyObject,
                    JsonConverters.Guid,
                    JsonConverters.DateTime,
                    JsonConverters.DateTimeOffset,
                    JsonConverters.TimeSpan,
                    JsonConverters.JsonElement,
                }
            };
            var json3 = JsonSerializer.Serialize(dy, options);
            Assert.AreEqual(json, json3);
            var jobj = JsonDocument.Parse(json3).RootElement;

            var json2 = JsonSerializer.Serialize(jobj, options);
            Assert.AreEqual(json, json2);

            var user = json.To<User>();
            Assert.AreEqual(1, user.Id);
            Assert.AreEqual("zijian666", user.Name);
            Assert.AreEqual(true, user.Enabled);
            var json4 = JsonSerializer.Serialize(user, options);
        }


        [TestMethod]
        public void 时间类型时区问题()
        {
            var a = "2023-07-01 18:05:03";
            var b = "2023-07-01 10:05:03 +00:00";
            var c = "2023-07-01 18:05:03 +08:00";

            Assert.AreEqual(a.To<DateTime>(), b.To<DateTime>());
            Assert.AreEqual(a.To<DateTime>(), c.To<DateTime>());

            Assert.AreEqual(a.To<DateTimeOffset>(), c.To<DateTimeOffset>());

            Assert.AreEqual(a.To<DateTime>(), b.To<DateTimeOffset>().To<DateTime>());
            Assert.AreEqual(a.To<DateTime>(), b.To<DateTimeOffset>().To<DateTime>());

        }

        [TestMethod]
        public void JSON大小写问题()
        {
            var json = "{\"name\":\"zijian666\"}";
            var user = json.To<User>();
            Assert.AreEqual("zijian666", user.Name);
        }

        [TestMethod]
        public void JSON数组对象字段值类型()
        {
            var factory = new ParsableConvertorFactory();
            var conv = factory.Create<int>();
            Assert.IsNotNull(conv.Convertor);
            Assert.IsInstanceOfType(conv.Convertor, typeof(ISpanParsableConvertor<int>));
        }
    }

    class User
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public bool Enabled { get; set; }
        public object Obj { get; set; } = new object();
        public object Null { get; set; } = null;

        public List<int> Numbers { get; set; }
    }
    internal class MyHashtable : Hashtable
    {

    }

    public interface IMyList<T> : IList<T>
    {

    }

    public interface IMyList : IList
    {

    }

    public class MyNameValueCollection : NameValueCollection
    {

    }


    public class Response : Dictionary<string, dynamic>, IEquatable<Response>
    {
        public bool Equals(Response? other)
        {
            if (other is null)
            {
                return false;
            }
            var id = Id;
            if (!string.IsNullOrWhiteSpace(id) && Id == other.Id)
            {
                return true;
            }
            var referenceId = ReferenceId;
            if (!string.IsNullOrWhiteSpace(referenceId) && referenceId == other.ReferenceId)
            {
                return true;
            }
            var userid = Data?["@user"]?.identity + "";
            return string.IsNullOrWhiteSpace(userid) && userid == (string?)other.Data?["@user"]?.identity + "";
        }

        public override bool Equals(object? obj)
        {
            return Equals(obj as Response);
        }

        public override int GetHashCode()
        {
            return this["id"].GetHashCode();
        }

        public static bool operator ==(Response? left, Response? right)
        {
            return EqualityComparer<Response>.Default.Equals(left!, right!);
        }

        public static bool operator !=(Response? left, Response? right)
        {
            return !(left == right);
        }

        public DateTime Date => this.GetValueOrDefault("date");
        public string Id => this.GetValueOrDefault("id", "");
        public string ReferenceId => this.GetValueOrDefault("reference_id", "");
        public string Message => this.GetValueOrDefault("message", "");
        public string[] Tags => this.GetValueOrDefault("tags", Array.Empty<string>());
        public string Type => this.GetValueOrDefault("type", "unknown");
        public dynamic? Data => this!.GetValueOrDefault("data", null);
    }
}
